import 'package:dio/dio.dart';
import 'package:get/get.dart';
import 'package:library_base/entities/generated/json/base/json_convert_content.dart';
import 'package:library_base/err/fb_error.dart';
import 'package:library_base/global/multi_language.dart';
import 'package:library_base/network/http_config.dart';
import 'package:library_base/network/http_util.dart';
import 'package:library_base/network/loading/request_loading.dart';
import 'package:library_base/network/transform/fb_parse_transform.dart';
import 'package:library_base/provider/multi_base_provide.dart';
import 'package:library_base/utils/toast_util.dart';
import 'package:library_base/utils/widget_generate_util.dart';

abstract class BaseController extends MultiBaseProvide {
  ///对象的运行时类型的表示
  String get className => runtimeType.toString();

  ///onResume 方法
  void onResume() {}

  ///onCreate方法， 只走一次， 这里就可以通过 [arguments] 拿到参数
  ///禁止在这里面做耗时阻塞操作
  void onCreate() {}

  void onPause() {}

  dynamic getArguments() => Get.arguments;

  Future onRefreshCallback() async {}

  Future onLoadCallback() async {}

  requestUniversal<T>(
    String url, {
    dynamic params,
    Map<String, dynamic>? queryParameters,
    Function(T cacheData)? cacheCallBack,
    RequestLoading? requestLoading,
    String? tipLoading,
    String? tipSuccess,
    String? tipFail = '网络异常',
    FBResultFul method = FBResultFul.POST,
    Options? options,
    bool isSendShowDialog = true,
    bool isShowDialogTip = false,
    bool isShowToastTip = false,
    bool isShowErrorDialogTip = false,
    bool isShowErrorToastTip = true,
    Function(String, int)? resultFailCall,
    Function(T)? resultSuccessCall,
    Function()? resultSuccessCallNoting,
    Function(List<T>)? resultSuccessListCall,
    Function(Map)? resultSuccessIfNoCode,
  }) {
    if (context == null) return;

    Future<Map>? fb;

    switch (method) {
      case FBResultFul.POST:
        fb = FBHttpUtil.post<Map>(context!, url,
            params: params,
            queryParameters: queryParameters,
            options: options,
            requestLoading: isSendShowDialog
                ? requestLoading ?? GenerateWidgetUtil.loadingDialog(context!)
                : null,
            transformer: FBParseTransform((result) => result));
        break;
      case FBResultFul.GET:
        fb = FBHttpUtil.get<Map>(context!, url,
            params: queryParameters,
            options: options,
            requestLoading: isSendShowDialog
                ? requestLoading ??
                    GenerateWidgetUtil.loadingDialog(context!,
                        content: tipLoading ?? MultiLanguage.loading.tr)
                : null,
            transformer: FBParseTransform((result) => result));
        break;
      case FBResultFul.DELETE:
        fb = FBHttpUtil.request<Map>(context!, url,
            FBResultFul.DELETE,
            queryParameters: queryParameters,
            params: params,
            options: options,
            requestLoading: isSendShowDialog
                ? requestLoading ?? GenerateWidgetUtil.loadingDialog(context!)
                : null,
            transformer: FBParseTransform((result) => result));
        break;

      case FBResultFul.PATCH:
      case FBResultFul.PUT:
        fb = FBHttpUtil.put<Map>(context!, url,
            params: params,
            queryParameters: queryParameters,
            options: options,
            requestLoading: isSendShowDialog
                ? requestLoading ?? GenerateWidgetUtil.loadingDialog(context!)
                : null,
            transformer: FBParseTransform((result) => result));
        break;
    }

    fb.then((value) {
      if (isStandardJson(value)) {
        if (value['code'] == HttpConfig.successCode) {
          success<T>(value, resultSuccessCall, resultSuccessCallNoting, resultSuccessListCall,
              isShowToastTip, tipSuccess, isShowDialogTip);
        } else {
          if (isShowErrorToastTip) {
            ToastUtil.error(value['msg']);
          } else if (isShowErrorDialogTip) {
            //todo
          }
          resultFailCall?.call(value['msg'], value['code']);
        }
      } else {
        ///假如没有code、data、msg这三个字段,则不是标准的json数据格式,需要自行处理逻辑
        if (resultSuccessIfNoCode != null) {
          resultSuccessIfNoCode(value);
        }
      }
    }).onError((error, stackTrace) {
      if(error is FBError){
        if (isShowErrorToastTip) {
          ToastUtil.error(error.message);
        } else if (isShowErrorDialogTip) {

        }
        resultFailCall?.call(error.message, error.code);
      }else{
        if(isSendShowDialog){
          ToastUtil.error(error.toString());
        }
      }
    });
  }

  ///判断是否自家的服务器标准的json格式,默认是有code和data即可
  bool isStandardJson(Map<dynamic, dynamic> data) {
    return data.containsKey('code') && data.containsKey('data') && data.containsKey('msg');
  }

  ///解析 对象 和 List两种情况,对象通过resultSuccessCall返回,集合通过resultSuccessListCall返回
  void success<T>(
    Map<dynamic, dynamic> value,
    Function(T)? resultSuccessCall,
    Function()? resultSuccessCallNoting,
    Function(List<T>)? resultSuccessListCall,
    bool isShowToastTip,
    String? tipSuccess,
    bool isShowDialogTip,
  ) {
    var data = value['data'];

    if (data is Map || data is bool) {
      if (resultSuccessCall != null && data != null) {
        resultSuccessCall(jsonConvert.convert<T>(value['data'])!);
      } else {
        resultSuccessCallNoting?.call();
      }
    } else if (data is List) {
      if (resultSuccessListCall != null) {
        resultSuccessListCall(jsonConvert.convertList<T>(data));
      }
    } else {
      throw const FormatException();
    }

    if (isShowToastTip) {
      ///弱提示,仅以toast显示
      ToastUtil.success(tipSuccess ?? MultiLanguage.loadedSuccessfully.tr);
    } else if (isShowDialogTip) {
      //todo 弹出窗口进行强提示
    }
  }

  ///异步请求，ui加载完以后会走一次这个放啊
  Future requestData() => Future.value();
}
